package com.moss.cloud.auth.biz.expand.miniapp;

import com.moss.cloud.auth.biz.exception.AuthErrorType;
import com.moss.cloud.auth.biz.service.ISysUserService;
import com.moss.cloud.auth.biz.utils.AuthHandel;
import com.moss.cloud.common.core.exception.SystemErrorType;
import com.moss.cloud.common.core.model.Result;
import com.moss.cloud.common.core.model.vo.UserInfo;
import com.moss.cloud.remote.api.model.from.WXUserTokenFrom;
import com.moss.cloud.remote.api.model.vo.WXUserJSCode;
import com.moss.cloud.remote.api.rpc.RemoteRpcService;
import lombok.Data;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;

import java.util.HashSet;

@Slf4j
@Data
public class MiniAppAuthenticationProvider implements AuthenticationProvider {
    private UserDetailsService userDetailsService;
    private RemoteRpcService remoteRpcService;
    private ISysUserService sysUserService;

    /**
     * 微信认证
     *
     * @param authentication
     * @return
     * @throws AuthenticationException
     */

    @SneakyThrows
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        MiniAppAuthenticationToken authenticationToken = (MiniAppAuthenticationToken) authentication;
        String code = (String) authenticationToken.getPrincipal();
        WXUserTokenFrom wxUserTokenFrom = new WXUserTokenFrom();
        wxUserTokenFrom.setCode(code);
        Result<WXUserJSCode> wxUserJSCodeResult = remoteRpcService.doOpenId(wxUserTokenFrom);
        AuthHandel.trueThrow(wxUserJSCodeResult.getCode().equals(SystemErrorType.WX_FAIL.getCode())).throwMessage(AuthErrorType.WEIXI_CODE_ERROR.getMesg());
        String openid = wxUserJSCodeResult.getData().getOpenid();
        String rawData = authenticationToken.getRawData();
        log.info("rawData:{}", rawData);
        UserInfo userInfo = sysUserService.userInfo(openid);
        // 微信用户不存在，提示注册------租户可在这里实现无用户拿到rawData去注册用户注册完成之后返回授权的token--授权token无需处理
        // rawData 是微信小程序通过 wx.getUserProfile 获得 在body中传递参数 key=rawData,
        // value={"nickName":"昵称","gender":0,"language":"zh_CN","city":"","province":"","country":"","avatarUrl":"头像"}
        AuthHandel.trueThrow(StringUtils.isBlank(userInfo.getOpenId())).throwMessage(AuthErrorType.WEIXI_USER_EMPTY.getMesg());
        UserDetails userDetails = userDetailsService.loadUserByUsername(openid);
        MiniAppAuthenticationToken result = new MiniAppAuthenticationToken(userDetails, new HashSet<>());
        result.setDetails(authentication.getDetails());
        return result;
    }


    @Override
    public boolean supports(Class<?> authentication) {
        return MiniAppAuthenticationToken.class.isAssignableFrom(authentication);
    }

}
